package cn.jobstart.common.word;

import cn.afterturn.easypoi.word.WordExportUtil;

import cn.jobstart.common.NumberUtil;
import cn.jobstart.common.SkList;
import cn.jobstart.common.StringUtil;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.util.TableTools;
import com.deepoove.poi.xwpf.NiceXWPFDocument;
import fr.opensagres.poi.xwpf.converter.pdf.PdfConverter;
import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author sunke
 * @Date 2020/7/29 14:51
 * @description
 */

public class WordUtils {



    public static int getPageCount(String docPath) {

        try{
            XWPFDocument docx = new XWPFDocument(new FileInputStream(docPath));



            int pageCount = docx.getProperties().getExtendedProperties().getUnderlyingProperties().getPages();




            return pageCount;
        }catch (Exception e){

        }
        return 0;


    }

    /**
     * 创建图片
     *
     * @param imgPath
     * @param w
     * @param h
     * @return
     */
    public static PictureRenderData getPicture(String imgPath, int w, int h) {

        return Pictures.ofLocal(imgPath).size(w, h)
                .create();

    }

    public static PictureRenderData getPicture(String imgPath) {
        return getPicture(imgPath, 100, 50);
    }


    /**
     * @param table    表格
     * @param titleLen 标题长度大于多少的才合并 如果0 全不合并
     * @param cells    要合并的列，如果是null 全部参与合并
     */
    public static void mergeCellsVertically(XWPFTable table, int titleLen, List<Integer> cells) {

        try {
            if (StringUtil.isNullOrEmpty(table)) {
                return;
            }

            //表格行数
            int rowSize = table.getNumberOfRows();

            //上一行的标题
            String preMergeName = "";
            String currentMergeName = "";


            int endRow = 0;
            int startRow = 0;

            if (rowSize <= 0) {
                return;
            }
            int cellSize = table.getRow(rowSize - 1).getTableCells().size();
            //  cellSize=1;
            for (int j = 0; j < cellSize; j++) {

                if (StringUtil.isNotObjEmpty(cells)) {

                    int finalJ = j;
                    //说明一个也没合并的列里，就跳过
                    if (cells.stream().noneMatch(index -> NumberUtil.parseInt(index) == finalJ)) {
                        continue;
                    }

                }


                //表格列数

                endRow = 0;
                startRow = 0;
                preMergeName = "";
                for (int i = 1; i < table.getNumberOfRows(); i++) {
                    try {
                        //当前标题
                        currentMergeName = StringUtil.toString(table.getRow(i).getCell(j).getText());

                        // System.out.println(i+","+j+":"+currentMergeName+","+startRow+","+endRow);
                        //如果相同就打个标识说明最后一项就是这个
                        if (
                                StringUtil.isNotObjEmpty(currentMergeName) &&

                                        preMergeName.equalsIgnoreCase(currentMergeName)) {

                            if (titleLen > 0 && currentMergeName.length() >= titleLen) {

                                endRow = i;
                            }
                        } else {
                            if (endRow > startRow) {
                                TableTools.mergeCellsVertically(table, j, startRow, endRow);
                            }
                            startRow = i; //开始行
                        }
                        preMergeName = currentMergeName;

                    } catch (Exception e) {
                        // e.printStackTrace();

                    }

                }

                if (endRow > startRow) {
                    TableTools.mergeCellsVertically(table, j, startRow, endRow);
                }


            }
        } catch (Exception e) {

        }

    }


    /**
     * @param template  模板文件
     * @param target    生成的文件
     * @param dataModel 数据
     */
    public static boolean createWord(String template, String target, IDataModel dataModel) {
        try {
            XWPFTemplate xwpfTemplate = XWPFTemplate.compile(template).render(dataModel);
            FileOutputStream out = new FileOutputStream(target);
            xwpfTemplate.write(out);
            out.flush();
            out.close();
            xwpfTemplate.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * @param target 生成的文件
     */
    public static boolean createWord(String templatePath, String target, Configure
            config, Map<String, Object> dataMap) {
        try {

            if (StringUtil.isNullOrEmpty(config)) {
                config = Configure.builder().useSpringEL().build();
            }
            XWPFTemplate template = XWPFTemplate.compile(templatePath, config).render(dataMap);
            template.writeToFile(target);


            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }



    public static  boolean createConfigChinese(String templatePath, OutputStream outputStream, Configure
            config, Map<String, Object> dataMap) throws Exception{

        if (StringUtil.isNullOrEmpty(config)) {
            config = Configure.builder().useSpringEL().build();
        }

        XWPFTemplate template = XWPFTemplate.compile(templatePath, config).render(dataMap);

        XWPFTemplate renew = XWPFTestSupport.readNewTemplate(template);

        renew.write(outputStream);
        renew.close();

        return true;



    }

    public static boolean createWord(String templatePath, OutputStream outputStream, Configure
            config, Map<String, Object> dataMap) {
        try {

            if (StringUtil.isNullOrEmpty(config)) {
                config = Configure.builder().useSpringEL().build();
            }

            XWPFTemplate template = XWPFTemplate.compile(templatePath, config).render(dataMap);



            template.write(outputStream);


            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    public static boolean createWord(String templatePath, OutputStream outputStream, Configure
            config, Map<String, Object> dataMap, WordListen wordListen) {
        try {
            if (StringUtil.isNullOrEmpty(config)) {
                config = Configure.builder().useSpringEL().build();
            }

            XWPFTemplate template = XWPFTemplate.compile(templatePath, config).render(dataMap);

            wordListen.receive(template);


            template.writeAndClose(outputStream);


            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 多个word 合并 生成 一个新的
     *
     * @param sourceList
     * @param target
     * @return
     */
    public static boolean mergeWord(List<String> sourceList, String target, boolean pageBreak) {
        try {
            if (sourceList == null || sourceList.size() == 0) {
                return false;
            }
            List<XWPFDocument> wordList = new ArrayList<>();
            Map<String, Object> map = new HashMap<>();
            XWPFDocument resultDoc;
            for (String source : sourceList) {
                XWPFDocument doc = WordExportUtil.exportWord07(source, map);
                wordList.add(doc);
            }
            resultDoc = WordUtils.mergeWord(wordList, pageBreak);
            FileOutputStream out = new FileOutputStream(target);
            resultDoc.write(out);
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    public static boolean mergeWordFromPoiTl(List<String> sourceList, String pageBreak, OutputStream out) throws Exception {


        if (StringUtil.isNullOrEmpty(sourceList)) {
            return false;
        }


        NiceXWPFDocument doc = null;

        //  NiceXWPFDocument main = new NiceXWPFDocument(new FileInputStream(sourceList.get(0)));


        NiceXWPFDocument breakDocument = null;
        if (StringUtil.isNotObjEmpty(pageBreak)) {
            breakDocument = new NiceXWPFDocument(new FileInputStream(pageBreak));
        }


        List<NiceXWPFDocument> docList = SkList.getInstance();
        NiceXWPFDocument mainDoc = new NiceXWPFDocument(new FileInputStream(sourceList.get(0)));
        for (int i = 1; i < sourceList.size(); i++) {
            if (StringUtil.isNotObjEmpty(breakDocument)) {
                docList.add(breakDocument);
            }
            NiceXWPFDocument subDoc = new NiceXWPFDocument(new FileInputStream(sourceList.get(i)));
            //   mainDoc = mainDoc.merge(subDoc);
            docList.add(subDoc);

        }


        mainDoc = mainDoc.merge(docList, mainDoc.createParagraph().createRun());


        mainDoc.write(out);
        mainDoc.close();
        out.close();










         /*doc= main.merge(breakDocument)
                    .merge(new NiceXWPFDocument(new FileInputStream(sourceList.get(1))))
                    .merge(breakDocument)
                    .merge(new NiceXWPFDocument(new FileInputStream(sourceList.get(2))));*/


        //  }





      /*  doc.write(out);
        doc.close();
        out.close();*/


        return true;


    }


    public static boolean mergeWord(List<String> sourceList, OutputStream out, boolean pageBreak) {
        try {
            if (sourceList == null || sourceList.size() == 0) {
                return false;
            }
            List<XWPFDocument> wordList = new ArrayList<>();

            XWPFDocument resultDoc;

            for (String source : sourceList) {

                XWPFDocument doc = new NiceXWPFDocument(new FileInputStream(source));
                //   XWPFDocument doc = WordExportUtil.exportWord07(source, map);

                wordList.add(doc);
            }
            resultDoc = WordUtils.mergeWord(wordList, pageBreak);

            resultDoc.write(out);
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 合并word 生成pdf
     *
     * @param sourceList
     * @param target
     * @return
     */
    public static boolean mergeWordToPdf(List<String> sourceList, String target) {


        if (mergeWord(sourceList, target + ".docx", true)) {
            wordToPdf(target + ".docx", target);
            File file = new File(target + ".docx");
            file.delete();
            return true;
        }

        return false;

    }


    /*   *//**
     * word to pdf
     *
     * @param source
     * @param target
     * @return
     *//*
    public static boolean wordToPdfFromAspose(String source, String target) {

        try {

            *//**
     * //新建一个空白pdf文档
     *//*
            File file = new File(target);
            FileOutputStream os = new FileOutputStream(file);
            //sourcerFile是将要被转化的word文档
            com.aspose.words.Document doc = new com.aspose.words.Document(source);
            //全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            doc.save(os, SaveFormat.PDF);
            os.close();
            return true;
        } catch (Exception e) {

            return false;
        }


    }*/


    /**
     * word to pdf
     *
     * @param source
     * @param target
     * @return
     */
    public static boolean wordToPdf(String source, String target) {
        try {
            FileInputStream fileInputStream = new FileInputStream(source);
            XWPFDocument xwpfDocument = new XWPFDocument(fileInputStream);
            PdfOptions pdfOptions = PdfOptions.create();

            FileOutputStream fileOutputStream = new FileOutputStream(target);
            PdfConverter.getInstance().convert(xwpfDocument, fileOutputStream, pdfOptions);
            fileInputStream.close();
            fileOutputStream.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * word文件合并
     *
     * @param wordList
     * @return
     * @throws Exception
     */

    public static XWPFDocument mergeWord(List<XWPFDocument> wordList, boolean pageBreak) throws Exception {

        if (CollectionUtils.isEmpty(wordList)) {

            throw new RuntimeException("待合并的word文档list为空");

        }
        XWPFDocument doc = wordList.get(0);
        int size = wordList.size();
        if (size > 1) {
            doc.createParagraph().setPageBreak(pageBreak);
        }
        for (int i = 1; i < size; i++) {
            // 从第二个word开始合并
            XWPFDocument nextPageDoc = wordList.get(i);

            if (pageBreak) {
                // 最后一页不需要设置分页符
                if (i != (size - 1)) {
                    nextPageDoc.createParagraph().setPageBreak(pageBreak);
                }
            }
            appendBody(doc, nextPageDoc);
        }
        //  }
        return doc;

    }

    private static void appendBody(XWPFDocument src, XWPFDocument append) throws Exception {
        CTBody src1Body = src.getDocument().getBody();
        CTBody src2Body = append.getDocument().getBody();
        List<XWPFPictureData> allPictures = append.getAllPictures();
        // 记录图片合并前及合并后的ID
        Map<String, String> map = new HashMap<>();
        for (XWPFPictureData picture : allPictures) {
            String before = append.getRelationId(picture);
            //将原文档中的图片加入到目标文档中
            String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);
            map.put(before, after);
        }
        appendBody(src1Body, src2Body, map);
    }

    private static void appendBody(CTBody src, CTBody append, Map<String, String> map) throws Exception {
        XmlOptions optionsOuter = new XmlOptions();
        optionsOuter.setSaveOuter();
        String appendString = append.xmlText(optionsOuter);
        String srcString = src.xmlText();
        String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
        String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
        String sufix = srcString.substring(srcString.lastIndexOf("<"));
        String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));
        if (map != null && !map.isEmpty()) {
            //对xml字符串中图片ID进行替换
            for (Map.Entry<String, String> set : map.entrySet()) {
                addPart = addPart.replace(set.getKey(), set.getValue());
            }
        }
        //将两个文档的xml内容进行拼接
       // CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
        XmlObject makeBody = XmlObject.Factory.parse(prefix + mainPart + addPart + sufix);
        src.set(makeBody);
    }
}
